#!/usr/bin/env python
# -*- coding: utf-8 -*-

from typing import Any

from cta.interface.action.close_position.abstract_close_position_action import AbstractClosePositionAction
from web.constants.close_position_reason import ClosePositionReason
from web.constants.datetime_format import DatetimeFormat
from web.constants.direction import Direction
from web.domain.responsibility_chain_dto import ResponsibilityChainDto
from web.manager.log_manager import LogManager
from web.models import CommodityFutureInfo
from web.models.commodity_future_date_contract_data import CommodityFutureDateContractData
from web.models.optimize2_commodity_future_transaction_record import Optimize2CommodityFutureTransactionRecord
from web.models.quant2_commodity_future_transaction_record import Quant2CommodityFutureTransactionRecord
from web.util.commodity_future_code_util import CommodityFutureCodeUtil
from web.util.datetime_util import DatetimeUtil

Logger = LogManager.get_logger(__name__)

class Optimize2MultiFactorClosePositionAction(AbstractClosePositionAction):
    """
    多因子策略，平仓期货
    """

    def exec(self, responsibility_chain_dto: ResponsibilityChainDto = None) -> Any:
        Logger.info("多因子策略，平仓期货")

        transaction_date: str = responsibility_chain_dto.transaction_date

        # 根据持仓时间，判断k线形态；判断当天是否应当平仓和开仓
        k_line_movement_pattern, close_or_open_position = self.optimize2_k_line_movement_pattern_and_close_or_open_position_by_holding_position_time(transaction_date)
        if not close_or_open_position:
            # if not self.close_or_open_position_by_up_down_percentage_with_n_date(transaction_date):
            Logger.info("日期[%s]不应当平仓和开仓", transaction_date)
            super().next(responsibility_chain_dto)
            return

        # 查询当天平仓的期货
        quant2_commodity_future_transaction_record_list: list[Quant2CommodityFutureTransactionRecord] = self.quant2_commodity_future_transaction_record_dao.find_close_position_by_date(transaction_date)
        if quant2_commodity_future_transaction_record_list is not None and len(quant2_commodity_future_transaction_record_list) > 0:
            for quant2_commodity_future_transaction_record in quant2_commodity_future_transaction_record_list:

                # 查询期货
                commodity_future_date_contract_data: CommodityFutureDateContractData = self.commodity_future_date_contract_data_dao.find_by_code_and_transaction_date(quant2_commodity_future_transaction_record.code, transaction_date)
                if commodity_future_date_contract_data is None:
                    Logger.warning("期货[%s]在日期[%s]没有交易记录，所以跳过", quant2_commodity_future_transaction_record.code, transaction_date)
                    continue

                # 查询commodity_future_info记录
                filter_dict = {'code__iexact': CommodityFutureCodeUtil.code_to_contract_code(commodity_future_date_contract_data.code)}
                commodity_future_info: CommodityFutureInfo = self.commodity_future_info_dao.find_one(filter_dict, dict(), list())

                # 查询optimize2_c_f_transact_record表中的记录
                optimize2_commodity_future_transaction_record: Optimize2CommodityFutureTransactionRecord = Optimize2CommodityFutureTransactionRecord()
                if quant2_commodity_future_transaction_record.direction == Direction.Up:
                    filter_dict = {'code': quant2_commodity_future_transaction_record.code, 'direction': Direction.Up, 'sell_date__isnull': True,
                                   'buy_date': quant2_commodity_future_transaction_record.buy_date, 'account_name': quant2_commodity_future_transaction_record.account_name}
                    optimize2_commodity_future_transaction_record = self.optimize2_commodity_future_transaction_record_dao.find_one(filter_dict, dict(), list())
                if quant2_commodity_future_transaction_record.direction == Direction.Down:
                    filter_dict = {'code': quant2_commodity_future_transaction_record.code, 'direction': Direction.Down, 'buy_date__isnull': True,
                                   'sell_date': quant2_commodity_future_transaction_record.sell_date, 'account_name': quant2_commodity_future_transaction_record.account_name}
                    optimize2_commodity_future_transaction_record = self.optimize2_commodity_future_transaction_record_dao.find_one(filter_dict, dict(), list())

                if optimize2_commodity_future_transaction_record is None:
                    Logger.warning("账户[%s]没持有期货[%s]，所以跳过", quant2_commodity_future_transaction_record.account_name, quant2_commodity_future_transaction_record.code)
                    continue

                # 更新optimize2_c_f_transact_record表的sell_date/buy_date、sell_price/buy_price、sell_lot/buy_lot、profit_and_loss和profit_and_loss_rate字段
                self.optimize2_commodity_future_transaction_record_dao.update_when_close_position(quant2_commodity_future_transaction_record.direction, transaction_date,
                                                                                                       commodity_future_date_contract_data.close_price, commodity_future_info,
                                                                                                       quant2_commodity_future_transaction_record.buy_lot if quant2_commodity_future_transaction_record.direction == Direction.Up else quant2_commodity_future_transaction_record.sell_lot,
                                                                                                       ClosePositionReason.Multi_Factor_Close_Position, optimize2_commodity_future_transaction_record.id_)
        else:
            Logger.warning("日期[%s]没有平仓的期货", transaction_date)

        super().next(responsibility_chain_dto)